#pragma once

#include<queue>
#include<pthread.h>

template <class T>
class BlockQueue
{
  private:
    std::queue<T> bq;
    int cap;
    pthread_cond_t have_space;   // 生产者
    pthread_cond_t have_data;    //消费者
    pthread_mutex_t mutex;
  private:
    bool IsFull()
    {
      return bq.size()==cap?true:false;
    }
    bool IsEmpty()
    {
      return bq.size()==0?true:false;
    }
  public:
    BlockQueue(int _cap)
      :cap(_cap)
    {
      pthread_cond_init(&have_space,nullptr);
      pthread_cond_init(&have_data,nullptr);
      pthread_mutex_init(&mutex,nullptr);

    }
    void Put(const T &s)
    {
      //生产数据
      pthread_mutex_lock(&mutex);
      //判断是否为满
      while(IsFull())
      {
       // std::cout<<"IsFull"<<std::endl;

        pthread_cond_wait(&have_space,&mutex);
      }
      //生产数据
      bq.push(s);
      //std::cout<<"create"<<std::endl;
      
      pthread_cond_signal(&have_data);

      pthread_mutex_unlock(&mutex);

    }
    void Take(T* s)
    {
      pthread_mutex_lock(&mutex);

      while(IsEmpty())
      {

        pthread_cond_wait(&have_data,&mutex);
      }
      //取出数据
      *s=bq.front();
      bq.pop();
      
      pthread_cond_signal(&have_space);

      pthread_mutex_unlock(&mutex);
    }
    ~BlockQueue()
    {
      pthread_cond_destroy(&have_space);
      pthread_cond_destroy(&have_data);
      pthread_mutex_destroy(&mutex);
    }
};
